<template>
  <div>
    <ul class="skin-list">
      <li
        v-for="item in skinData"
        :key="item.id"
        @click="changeTheme(item)"
      >
        <sc-icon
          name="icontianjiawancheng"
          v-if="item.color === storageTheme"
        ></sc-icon>
      </li>
    </ul>
  </div>
</template>

<script>
import { setTheme } from '@/api/user';
const version = require('element-ui/package.json').version;
const ORIGINAL_THEME = '#409EFF';
export default {
  data() {
    return {
      chalk: '',
      theme: ORIGINAL_THEME,
      storageTheme: (localStorage.getItem('theme') || '#409EFF').toLowerCase(),
      skinData: [
        {
          id: 1,
          color: '#3378ff' //蓝
        },
        {
          id: 2,
          color: '#12b9b8' //绿
        },
        {
          id: 3,
          color: '#9b39ee' //紫
        }
      ]
    };
  },
  created() {
    // 加载上次保存的肤色
    let defaultTheme = localStorage.getItem('theme') || '#409EFF';
    if (defaultTheme) {
      this.theme = defaultTheme;
    }
  },
  watch: {
    // 监听主题色的变化
    async theme(val) {
      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME;
      if (typeof val !== 'string') return;
      const themeCluster = this.getThemeCluster(val.replace('#', ''));
      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''));

      const getHandler = (variable, id) => {
        return () => {
          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''));
          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster);
          let styleTag = document.getElementById(id);
          if (!styleTag) {
            styleTag = document.createElement('style');
            styleTag.setAttribute('id', id);
            document.head.appendChild(styleTag);
          }
          styleTag.innerText = newStyle;
        };
      };
      if (!this.chalk) {
        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
        await this.getCSSString(url, 'chalk');
      }
      const chalkHandler = getHandler('chalk', 'chalk-style');
      chalkHandler();
      const styles = [].slice.call(document.querySelectorAll('style')).filter(style => {
        const text = style.innerText;
        return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text);
      });
      styles.forEach(style => {
        const { innerText } = style;
        if (typeof innerText !== 'string') return;
        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster);
      });

      localStorage.setItem('theme', val);
      this.$store.dispatch('changeTheme', val);

      let data = {
        type: 'changeTheme',
        data: {
          theme: val
        }
      };

      let parentOrigin = document.referrer;
      window.parent.postMessage(data, parentOrigin);
    }
  },
  methods: {
    // 修改主题
    changeTheme(item) {
      setTheme({
        theme: item.color
      }).then(res => {
        this.theme = item.color;
        this.storageTheme = item.color;
      });
    },
    // 更新样式
    updateStyle(style, oldCluster, newCluster) {
      let newStyle = style;
      oldCluster.forEach((color, index) => {
        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]);
      });
      return newStyle;
    },
    // 获取样式
    getCSSString(url, variable) {
      return new Promise(resolve => {
        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4 && xhr.status === 200) {
            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '');
            resolve();
          }
        };
        xhr.open('GET', url);
        xhr.send();
      });
    },
    // 获取并生成对应样式
    getThemeCluster(theme) {
      const tintColor = (color, tint) => {
        let red = parseInt(color.slice(0, 2), 16);
        let green = parseInt(color.slice(2, 4), 16);
        let blue = parseInt(color.slice(4, 6), 16);
        if (tint === 0) {
          return [red, green, blue].join(',');
        } else {
          red += Math.round(tint * (255 - red));
          green += Math.round(tint * (255 - green));
          blue += Math.round(tint * (255 - blue));
          red = red.toString(16);
          green = green.toString(16);
          blue = blue.toString(16);
          return `#${red}${green}${blue}`;
        }
      };
      const shadeColor = (color, shade) => {
        let red = parseInt(color.slice(0, 2), 16);
        let green = parseInt(color.slice(2, 4), 16);
        let blue = parseInt(color.slice(4, 6), 16);
        red = Math.round((1 - shade) * red);
        green = Math.round((1 - shade) * green);
        blue = Math.round((1 - shade) * blue);
        red = red.toString(16);
        green = green.toString(16);
        blue = blue.toString(16);
        return `#${red}${green}${blue}`;
      };
      const clusters = [theme];
      for (let i = 0; i <= 9; i++) {
        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
      }
      clusters.push(shadeColor(theme, 0.1));
      return clusters;
    }
  }
};
</script>

<style lang="scss" scoped>
.skin-list {
  display: flex;
  gap: 10px;

  li {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    color: #fff;
    background-color: #ccc;

    &:nth-of-type(1) {
      background: linear-gradient(90.08deg, #179eff 2.85%, #4e54c8 97.4%);
    }

    &:nth-of-type(2) {
      background: linear-gradient(90.05deg, #06beb6 2.67%, #31aebe 95.88%);
    }

    &:nth-of-type(3) {
      background: linear-gradient(90.08deg, #a53cf8 2.85%, #6b2cbb 97.4%);
    }

    i {
      font-size: 12px;
    }
  }
}
</style>
